﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Net;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Vit.Common.Helpers
{
    public class WebHelper
    {
        public readonly static TimeSpan CACHE_DURATION = TimeSpan.FromDays(30);
        public static Dictionary<string, string> MimeTypeMappings = new Dictionary<string, string>();

        public static string ResolveServerUrl(string url)
        {
            return url.StartsWith("~/") ? url : VirtualPathUtility.Combine("~/", url);
        }

        public static string ResolveRootUrl(string url)
        {
            if (url.StartsWith("~/"))
                url = url.TrimStart('~');
            if (VirtualPathUtility.IsAbsolute(url) == false)
                url = ResolveClientUrl(url);

            return string.Concat(HttpContext.Current.Request.ApplicationPath.TrimEnd('/'), url);
        }

        public static string ResolveFullUrl(string url)
        {
            if (url.StartsWith(HttpContext.Current.Request.Url.Scheme + "://"))
                return url;
            if (url.StartsWith("~/"))
                url = url.TrimStart('~');

            string root = string.Format("{0}://{1}{2}", HttpContext.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Authority, HttpContext.Current.Request.ApplicationPath);

            if (VirtualPathUtility.IsAbsolute(url) == false)
                url = ResolveClientUrl(url);
            return string.Concat(root, url);
        }

        public static string ResolveClientUrl(string url)
        {
            return VirtualPathUtility.MakeRelative(HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath, url);
        }

        public static string PhysicalPath(string url)
        {
            if (HttpContext.Current == null)
                return url;
            if (url.StartsWith(HttpContext.Current.Request.PhysicalApplicationPath))
                return url;
            if (VirtualPathUtility.IsAbsolute(url) == false)
                url = VirtualPathUtility.MakeRelative(HttpContext.Current.Request.ApplicationPath, url);
            if (!url.StartsWith("~/"))
                url = "~/" + url.TrimStart('/');
            return HttpContext.Current.Server.MapPath(url);
        }

        public static bool IsPhysicalUrlExists(string url)
        {
            string file = PhysicalPath(url);
            return File.Exists(file);
        }

        public static void EnsureMimeTypeMappings()
        {
            if (MimeTypeMappings.Count <= 0)
            {
                MimeTypeMappings.Add("*", "application/octet-stream");
                MimeTypeMappings.Add("323", "text/h323");
                MimeTypeMappings.Add("acx", "application/internet-property-stream");
                MimeTypeMappings.Add("ai", "application/postscript");
                MimeTypeMappings.Add("aif", "audio/x-aiff");
                MimeTypeMappings.Add("aifc", "audio/x-aiff");
                MimeTypeMappings.Add("aiff", "audio/x-aiff");
                MimeTypeMappings.Add("asf", "video/x-ms-asf");
                MimeTypeMappings.Add("asr", "video/x-ms-asf");
                MimeTypeMappings.Add("asx", "video/x-ms-asf");
                MimeTypeMappings.Add("au", "audio/basic");
                MimeTypeMappings.Add("avi", "video/x-msvideo");
                MimeTypeMappings.Add("axs", "application/olescript");
                MimeTypeMappings.Add("bas", "text/plain");
                MimeTypeMappings.Add("bcpio", "application/x-bcpio");
                MimeTypeMappings.Add("bin", "application/octet-stream");
                MimeTypeMappings.Add("bmp", "image/bmp");
                MimeTypeMappings.Add("c", "text/plain");
                MimeTypeMappings.Add("cat", "application/vnd.ms-pkiseccat");
                MimeTypeMappings.Add("cdf", "application/x-cdf");
                MimeTypeMappings.Add("cer", "application/x-x509-ca-cert");
                MimeTypeMappings.Add("class", "application/octet-stream");
                MimeTypeMappings.Add("clp", "application/x-msclip");
                MimeTypeMappings.Add("cmx", "image/x-cmx");
                MimeTypeMappings.Add("cod", "image/cis-cod");
                MimeTypeMappings.Add("cpio", "application/x-cpio");
                MimeTypeMappings.Add("crd", "application/x-mscardfile");
                MimeTypeMappings.Add("crl", "application/pkix-crl");
                MimeTypeMappings.Add("crt", "application/x-x509-ca-cert");
                MimeTypeMappings.Add("csh", "application/x-csh");
                MimeTypeMappings.Add("css", "text/css");
                MimeTypeMappings.Add("dcr", "application/x-director");
                MimeTypeMappings.Add("der", "application/x-x509-ca-cert");
                MimeTypeMappings.Add("dir", "application/x-director");
                MimeTypeMappings.Add("dll", "application/x-msdownload");
                MimeTypeMappings.Add("dms", "application/octet-stream");
                MimeTypeMappings.Add("doc", "application/msword");
                MimeTypeMappings.Add("dot", "application/msword");
                MimeTypeMappings.Add("dvi", "application/x-dvi");
                MimeTypeMappings.Add("dxr", "application/x-director");
                MimeTypeMappings.Add("eps", "application/postscript");
                MimeTypeMappings.Add("etx", "text/x-setext");
                MimeTypeMappings.Add("evy", "application/envoy");
                MimeTypeMappings.Add("exe", "application/octet-stream");
                MimeTypeMappings.Add("fif", "application/fractals");
                MimeTypeMappings.Add("flr", "x-world/x-vrml");
                MimeTypeMappings.Add("gif", "image/gif");
                MimeTypeMappings.Add("gtar", "application/x-gtar");
                MimeTypeMappings.Add("gz", "application/x-gzip");
                MimeTypeMappings.Add("h", "text/plain");
                MimeTypeMappings.Add("hdf", "application/x-hdf");
                MimeTypeMappings.Add("hlp", "application/winhlp");
                MimeTypeMappings.Add("hqx", "application/mac-binhex40");
                MimeTypeMappings.Add("hta", "application/hta");
                MimeTypeMappings.Add("htc", "text/x-component");
                MimeTypeMappings.Add("htm", "text/html");
                MimeTypeMappings.Add("html", "text/html");
                MimeTypeMappings.Add("htt", "text/webviewhtml");
                MimeTypeMappings.Add("ico", "image/x-icon");
                MimeTypeMappings.Add("ief", "image/ief");
                MimeTypeMappings.Add("iii", "application/x-iphone");
                MimeTypeMappings.Add("ins", "application/x-internet-signup");
                MimeTypeMappings.Add("isp", "application/x-internet-signup");
                MimeTypeMappings.Add("jfif", "image/pipeg");
                MimeTypeMappings.Add("jpe", "image/jpeg");
                MimeTypeMappings.Add("jpeg", "image/jpeg");
                MimeTypeMappings.Add("jpg", "image/jpeg");
                MimeTypeMappings.Add("js", "application/x-javascript");
                MimeTypeMappings.Add("latex", "application/x-latex");
                MimeTypeMappings.Add("lha", "application/octet-stream");
                MimeTypeMappings.Add("lsf", "video/x-la-asf");
                MimeTypeMappings.Add("lsx", "video/x-la-asf");
                MimeTypeMappings.Add("lzh", "application/octet-stream");
                MimeTypeMappings.Add("m13", "application/x-msmediaview");
                MimeTypeMappings.Add("m14", "application/x-msmediaview");
                MimeTypeMappings.Add("m3u", "audio/x-mpegurl");
                MimeTypeMappings.Add("man", "application/x-troff-man");
                MimeTypeMappings.Add("mdb", "application/x-msaccess");
                MimeTypeMappings.Add("me", "application/x-troff-me");
                MimeTypeMappings.Add("mht", "message/rfc822");
                MimeTypeMappings.Add("mhtml", "message/rfc822");
                MimeTypeMappings.Add("mid", "audio/mid");
                MimeTypeMappings.Add("mny", "application/x-msmoney");
                MimeTypeMappings.Add("mov", "video/quicktime");
                MimeTypeMappings.Add("movie", "video/x-sgi-movie");
                MimeTypeMappings.Add("mp2", "video/mpeg");
                MimeTypeMappings.Add("mp3", "audio/mpeg");
                MimeTypeMappings.Add("mpa", "video/mpeg");
                MimeTypeMappings.Add("mpe", "video/mpeg");
                MimeTypeMappings.Add("mpeg", "video/mpeg");
                MimeTypeMappings.Add("mpg", "video/mpeg");
                MimeTypeMappings.Add("mpp", "application/vnd.ms-project");
                MimeTypeMappings.Add("mpv2", "video/mpeg");
                MimeTypeMappings.Add("ms", "application/x-troff-ms");
                MimeTypeMappings.Add("mvb", "application/x-msmediaview");
                MimeTypeMappings.Add("nws", "message/rfc822");
                MimeTypeMappings.Add("oda", "application/oda");
                MimeTypeMappings.Add("p10", "application/pkcs10");
                MimeTypeMappings.Add("p12", "application/x-pkcs12");
                MimeTypeMappings.Add("p7b", "application/x-pkcs7-certificates");
                MimeTypeMappings.Add("p7c", "application/x-pkcs7-mime");
                MimeTypeMappings.Add("p7m", "application/x-pkcs7-mime");
                MimeTypeMappings.Add("p7r", "application/x-pkcs7-certreqresp");
                MimeTypeMappings.Add("p7s", "application/x-pkcs7-signature");
                MimeTypeMappings.Add("pbm", "image/x-portable-bitmap");
                MimeTypeMappings.Add("pdf", "application/pdf");
                MimeTypeMappings.Add("pfx", "application/x-pkcs12");
                MimeTypeMappings.Add("pgm", "image/x-portable-graymap");
                MimeTypeMappings.Add("pko", "application/ynd.ms-pkipko");
                MimeTypeMappings.Add("pma", "application/x-perfmon");
                MimeTypeMappings.Add("pmc", "application/x-perfmon");
                MimeTypeMappings.Add("pml", "application/x-perfmon");
                MimeTypeMappings.Add("pmr", "application/x-perfmon");
                MimeTypeMappings.Add("pmw", "application/x-perfmon");
                MimeTypeMappings.Add("pnm", "image/x-portable-anymap");
                MimeTypeMappings.Add("pot", "application/vnd.ms-powerpoint");
                MimeTypeMappings.Add("ppm", "image/x-portable-pixmap");
                MimeTypeMappings.Add("pps", "application/vnd.ms-powerpoint");
                MimeTypeMappings.Add("ppt", "application/vnd.ms-powerpoint");
                MimeTypeMappings.Add("prf", "application/pics-rules");
                MimeTypeMappings.Add("ps", "application/postscript");
                MimeTypeMappings.Add("pub", "application/x-mspublisher");
                MimeTypeMappings.Add("qt", "video/quicktime");
                MimeTypeMappings.Add("ra", "audio/x-pn-realaudio");
                MimeTypeMappings.Add("ram", "audio/x-pn-realaudio");
                MimeTypeMappings.Add("ras", "image/x-cmu-raster");
                MimeTypeMappings.Add("rgb", "image/x-rgb");
                MimeTypeMappings.Add("rmi", "audio/mid");
                MimeTypeMappings.Add("roff", "application/x-troff");
                MimeTypeMappings.Add("rtf", "application/rtf");
                MimeTypeMappings.Add("rtx", "text/richtext");
                MimeTypeMappings.Add("scd", "application/x-msschedule");
                MimeTypeMappings.Add("sct", "text/scriptlet");
                MimeTypeMappings.Add("setpay", "application/set-payment-initiation");
                MimeTypeMappings.Add("setreg", "application/set-registration-initiation");
                MimeTypeMappings.Add("sh", "application/x-sh");
                MimeTypeMappings.Add("shar", "application/x-shar");
                MimeTypeMappings.Add("sit", "application/x-stuffit");
                MimeTypeMappings.Add("snd", "audio/basic");
                MimeTypeMappings.Add("spc", "application/x-pkcs7-certificates");
                MimeTypeMappings.Add("spl", "application/futuresplash");
                MimeTypeMappings.Add("src", "application/x-wais-source");
                MimeTypeMappings.Add("sst", "application/vnd.ms-pkicertstore");
                MimeTypeMappings.Add("stl", "application/vnd.ms-pkistl");
                MimeTypeMappings.Add("stm", "text/html");
                MimeTypeMappings.Add("sv4cpio", "application/x-sv4cpio");
                MimeTypeMappings.Add("sv4crc", "application/x-sv4crc");
                MimeTypeMappings.Add("t", "application/x-troff");
                MimeTypeMappings.Add("tar", "application/x-tar");
                MimeTypeMappings.Add("tcl", "application/x-tcl");
                MimeTypeMappings.Add("tex", "application/x-tex");
                MimeTypeMappings.Add("texi", "application/x-texinfo");
                MimeTypeMappings.Add("texinfo", "application/x-texinfo");
                MimeTypeMappings.Add("tgz", "application/x-compressed");
                MimeTypeMappings.Add("tif", "image/tiff");
                MimeTypeMappings.Add("tiff", "image/tiff");
                MimeTypeMappings.Add("tr", "application/x-troff");
                MimeTypeMappings.Add("trm", "application/x-msterminal");
                MimeTypeMappings.Add("tsv", "text/tab-separated-values");
                MimeTypeMappings.Add("txt", "text/plain");
                MimeTypeMappings.Add("uls", "text/iuls");
                MimeTypeMappings.Add("ustar", "application/x-ustar");
                MimeTypeMappings.Add("vcf", "text/x-vcard");
                MimeTypeMappings.Add("vrml", "x-world/x-vrml");
                MimeTypeMappings.Add("wav", "audio/x-wav");
                MimeTypeMappings.Add("wcm", "application/vnd.ms-works");
                MimeTypeMappings.Add("wdb", "application/vnd.ms-works");
                MimeTypeMappings.Add("wks", "application/vnd.ms-works");
                MimeTypeMappings.Add("wmf", "application/x-msmetafile");
                MimeTypeMappings.Add("wps", "application/vnd.ms-works");
                MimeTypeMappings.Add("wri", "application/x-mswrite");
                MimeTypeMappings.Add("wrl", "x-world/x-vrml");
                MimeTypeMappings.Add("wrz", "x-world/x-vrml");
                MimeTypeMappings.Add("xaf", "x-world/x-vrml");
                MimeTypeMappings.Add("xbm", "image/x-xbitmap");
                MimeTypeMappings.Add("xla", "application/vnd.ms-excel");
                MimeTypeMappings.Add("xlc", "application/vnd.ms-excel");
                MimeTypeMappings.Add("xlm", "application/vnd.ms-excel");
                MimeTypeMappings.Add("xls", "application/vnd.ms-excel");
                MimeTypeMappings.Add("xlt", "application/vnd.ms-excel");
                MimeTypeMappings.Add("xlw", "application/vnd.ms-excel");
                MimeTypeMappings.Add("xof", "x-world/x-vrml");
                MimeTypeMappings.Add("xpm", "image/x-xpixmap");
                MimeTypeMappings.Add("xwd", "image/x-xwindowdump");
                MimeTypeMappings.Add("z", "application/x-compress");
                MimeTypeMappings.Add("zip", "application/zip");
            }
      }

        public static string GetMimeType(string extension)
        {
            EnsureMimeTypeMappings();
            extension = extension.ToLower();
            if (extension.StartsWith("."))
                extension = extension.TrimStart('.');
            else
            {
                int idx = extension.LastIndexOf('.');
                extension = extension.Substring(idx + 1);
            }
            if (MimeTypeMappings.ContainsKey(extension))
                return MimeTypeMappings[extension];
            return "application/octet-stream";
        }

        public static byte[] GetFileBytes(HttpContext context, string virtualPath, bool compressed)
        {
            byte[] bytes = null;
            if (File.Exists(context.Server.MapPath(virtualPath)))
            {
                using (MemoryStream memoryStream = new MemoryStream(5000))
                {
                    using (Stream writer = compressed ?
                        (Stream)(new GZipStream(memoryStream, CompressionMode.Compress)) :
                        memoryStream)
                    {
                        byte[] fileBytes = GetFileBytes(context, virtualPath);
                        writer.Write(fileBytes, 0, fileBytes.Length);
                        writer.Close();
                    }

                    bytes = memoryStream.ToArray();
                }
            }
            return bytes;
        }

        public static byte[] GetFileBytes(HttpContext context, string virtualPath)
        {
            if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
            {
                using (WebClient client = new WebClient())
                {
                    return client.DownloadData(virtualPath);
                }
            }
            else
            {
                string physicalPath = PhysicalPath(virtualPath);
                if (File.Exists(physicalPath))
                {
                    byte[] bytes = File.ReadAllBytes(physicalPath);
                    return bytes;
                }
            }
            return null;
        }

        public static void WriteResponseBytes(HttpContext context, byte[] bytes, bool isCompressed, string contentType)
        {
            HttpResponse response = context.Response;

            response.AppendHeader("Content-Length", bytes.Length.ToString());
            response.ContentType = contentType;
            if (isCompressed)
                response.AppendHeader("Content-Encoding", "gzip");

            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetExpires(DateTime.Now.Add(CACHE_DURATION));
            context.Response.Cache.SetMaxAge(CACHE_DURATION);
            context.Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");

            response.OutputStream.Write(bytes, 0, bytes.Length);
            response.Flush();
        }

        public static bool CanGZip(HttpContext context)
        {
            string acceptEncoding = context.Request.Headers["Accept-Encoding"];
            if (!string.IsNullOrEmpty(acceptEncoding) &&
                 (acceptEncoding.Contains("gzip") || acceptEncoding.Contains("deflate")))
                return true;
            return false;
        }

        public static void InsertObjectToCache(string cacheKey, object obj)
        {
            if (obj == null)
                return;
            HttpContext.Current.Cache.Insert(cacheKey,
            obj, null, System.Web.Caching.Cache.NoAbsoluteExpiration,
            CACHE_DURATION);
        }

        public static object GetCachedObject(string cacheKey)
        {
            return HttpContext.Current.Cache[cacheKey];
        }
    }
}
